package com.xxx.springboot.controller;

import java.util.Calendar;
import java.util.Date;
import java.util.UUID;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.xxx.springboot.annotation.NotRepeatSubmit;
import com.xxx.springboot.pojo.token.AccessToken;
import com.xxx.springboot.pojo.token.ApiResponse;
import com.xxx.springboot.pojo.token.AppInfo;
import com.xxx.springboot.pojo.token.TokenInfo;
import com.xxx.springboot.pojo.token.UserInfo;
import com.xxx.springboot.util.JsonUtil;
import com.xxx.springboot.util.MD5Util;
import com.xxx.springboot.util.RedisUtil;

import lombok.extern.slf4j.Slf4j;

/**
 * 令牌token相关Controller
 * 
 * https://mp.weixin.qq.com/s?__biz=MjM5NzMyMjAwMA==&mid=2651488128&idx=1&sn=89dbe5a640db65a34e1d0a279af2d5af&chksm=bd2513ff8a529ae90558495f8849ff0dafd378671c124cbf36909e0ed559728ce41820299938&scene=21#wechat_redirect
 */
@Slf4j
@RestController
@RequestMapping("/api/token")
public class TokenController {
	
	/**
	 * 获取token
	 * @param timestamp
	 * @param appId
	 * @param appSecret
	 * @return
	 */
	@PostMapping("/api_token")
	public ApiResponse<AccessToken> apiToken(
			@RequestHeader("timestamp") String timestamp,
			@RequestHeader("sign") String sign,
			String appId, String appSecret) {
		log.info("appId:{}, timestamp:{}, appSecret:{}", appId, timestamp, appSecret);
		long reqeustInterval = System.currentTimeMillis() - Long.valueOf(timestamp);
		if(reqeustInterval>1000*60) { // 超时时间：60s
			System.out.println("request timeout");
		}
		
		// 1. 根据appId查询数据库获取appSecret
		AppInfo appInfo = new AppInfo(appId, appSecret);
		// 2. 校验签名
		String signString = timestamp + appId + appInfo.getKey();
		String signature = MD5Util.MD5_32(signString);
		if(!sign.equals(signature)) {
			System.out.println("error sign");
		}
		// 3. 如果正确生成一个token保存到redis中，如果错误返回错误信息
		AccessToken accessToken = this.saveToken(0, appInfo, null);
		log.info("accessToken:{}", accessToken);
		return ApiResponse.success(accessToken);
	}

	@NotRepeatSubmit(5000)
	@PostMapping("user_token")
	public ApiResponse<UserInfo> userToken(String appId, String appSecret, String username, String password) {
		// 根据用户名查询密码, 并比较密码(密码可以RSA加密一下)
		UserInfo userInfo = new UserInfo(username, password, "123abc");
		String pwd = password + userInfo.getSalt();
		String passwordMD5 = MD5Util.MD5_32(pwd);
		// 2. 保存Token
		AppInfo appInfo = new AppInfo(appId, appSecret);
		AccessToken accessToken = this.saveToken(1, appInfo, userInfo);
		userInfo.setAccessToken(accessToken);
		log.info("accessToken:{}", accessToken);
		return ApiResponse.success(userInfo);
	}

	private AccessToken saveToken(int tokenType, AppInfo appInfo, UserInfo userInfo) {
		String token = UUID.randomUUID().toString();
		// 设置token有效期为2小时
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(new Date());
		calendar.add(Calendar.SECOND, 7200);
		Date expireTime = calendar.getTime();
		// 保存token信息到redis中
		TokenInfo tokenInfo = new TokenInfo();
		tokenInfo.setTokenType(tokenType);
		tokenInfo.setAppInfo(appInfo);
		if (tokenType == 1) {
			tokenInfo.setUserInfo(userInfo);
		}
		String value = JsonUtil.encodeJson(tokenInfo);
		RedisUtil.set(token, value, 7200);
		AccessToken accessToken = new AccessToken(token, expireTime);
		return accessToken;
	}

}
